﻿#include <io.h>
#include <fcntl.h>

#include <atlbase.h>
#include <atlwin.h>

#include <iostream>
#include <vector>

static const std::wstring kRootKeyName = LR"(SYSTEM\CurrentControlSet\Control\Class\{4d36e96c-e325-11ce-bfc1-08002be10318})";

struct GlobalSettings
{
	std::wstring reg_key_name;
	std::wstring provider_name;
	std::vector<BYTE> enable_dynamic_devices;
};

struct RegKey
{

};

int main(int argc, TCHAR* argv[])
{
	// SetConsoleTitle(L"Disable front panel jack detection");
	SetConsoleTitle(L"禁用前面板插孔检测");
	(void)_setmode(_fileno(stdout), _O_U16TEXT);

	CRegKey reg_key;
	auto status = reg_key.Open(HKEY_LOCAL_MACHINE, kRootKeyName.c_str());
	if (status != ERROR_SUCCESS)
	{
		return -1;
	}
	DWORD sub_key_len = MAX_PATH;
	TCHAR sub_key_name[MAX_PATH] = { 0 };
	std::vector<GlobalSettings> global_settings_vec;
	for (auto index = 0; reg_key.EnumKey(index, sub_key_name, &sub_key_len) != ERROR_NO_MORE_ITEMS; ++index, sub_key_len = MAX_PATH)
	{
		std::wstring sub_reg_key_name = kRootKeyName + L"\\" + sub_key_name;

		CRegKey sub_reg_key;
		status = sub_reg_key.Open(HKEY_LOCAL_MACHINE, sub_reg_key_name.c_str());
		if (status != ERROR_SUCCESS)
		{
			continue;
		}

		CRegKey final_reg_key;
		std::wstring final_reg_key_name = sub_reg_key_name + L"\\GlobalSettings";
		status = final_reg_key.Open(HKEY_LOCAL_MACHINE, final_reg_key_name.c_str());
		if (status != ERROR_SUCCESS)
		{
			continue;
		}

		ULONG sub_str_len = MAX_PATH;
		TCHAR sub_str_value[MAX_PATH] = { 0 };
		status = sub_reg_key.QueryStringValue(L"ProviderName", sub_str_value, &sub_str_len);
		if (status != ERROR_SUCCESS)
		{
			continue;
		}

		ULONG sub_bin_len = MAX_PATH;
		BYTE sub_bin_value[MAX_PATH] = { 0 };
		status = final_reg_key.QueryBinaryValue(L"EnableDynamicDevices", sub_bin_value, &sub_bin_len);
		if (status != ERROR_SUCCESS)
		{
			continue;
		}

		GlobalSettings global_settings = { final_reg_key_name,sub_str_value,
			std::vector<BYTE>(sub_bin_value,sub_bin_value + sub_bin_len) };
		// global_settings.enable_dynamic_devices.assign(sub_bin_value, sub_bin_value + sub_bin_len);
		global_settings_vec.emplace_back(std::move(global_settings));
	}

	if (global_settings_vec.empty())
	{
		return -2;
	}

	// std::wcout << L"[x] Represents enabled [ ] Represents disabled" << std::endl;
	std::wcout << L"[x] 代表已开启 [ ] 代表已禁用" << std::endl;
	size_t number = 0;
	do
	{
		for (size_t index = 0; index < global_settings_vec.size(); index++)
		{
			number = (index + 1);
			auto& global_settings = global_settings_vec.at(index);
			auto& provider_name = global_settings.provider_name;
			auto& enable_dynamic_devices = global_settings.enable_dynamic_devices;
			while (enable_dynamic_devices.size() < sizeof(ULONG))
			{
				enable_dynamic_devices.push_back(0);
			}
			auto is_enable_dynamic_devices = *((ULONG*)enable_dynamic_devices.data());
			if (is_enable_dynamic_devices)
			{
				std::wcout << number << L". [x] " << provider_name << std::endl;
			}
			else
			{
				std::wcout << number << L". [ ] " << provider_name << std::endl;
			}
		}
		//std::wcout << L"Please enter a number (0 for exit) enable or disable: ";
		std::wcout << L"请输入编号 (0 退出) 开启或禁用: ";
		std::wcin >> number;
		if (number > 0 && number <= global_settings_vec.size())
		{
			auto& global_settings = global_settings_vec.at(number - 1);
			auto& enable_dynamic_devices = global_settings.enable_dynamic_devices;

			CRegKey final_reg_key;
			std::wstring final_reg_key_name = global_settings.reg_key_name;
			status = final_reg_key.Open(HKEY_LOCAL_MACHINE, final_reg_key_name.c_str());
			if (status != ERROR_SUCCESS)
			{
				return -3;
			}
			while (enable_dynamic_devices.size() < sizeof(ULONG))
			{
				enable_dynamic_devices.push_back(0);
			}
			auto is_enable_dynamic_devices = *((ULONG*)enable_dynamic_devices.data());
			if (is_enable_dynamic_devices)
			{
				enable_dynamic_devices = std::vector<BYTE>{ 0, 0, 0, 0 };
			}
			else
			{
				enable_dynamic_devices = std::vector<BYTE>{ 1, 0, 0, 0 };
			}

			status = final_reg_key.SetBinaryValue(L"EnableDynamicDevices", enable_dynamic_devices.data(), (ULONG)enable_dynamic_devices.size());
			if (status != ERROR_SUCCESS)
			{
				return -4;
			}

			auto std_out_handle = GetStdHandle(STD_OUTPUT_HANDLE);
			CONSOLE_SCREEN_BUFFER_INFO console_screen_buffer_info;
			if (!GetConsoleScreenBufferInfo(std_out_handle, &console_screen_buffer_info))
			{
				return -5;
			}
			// FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED
			auto foreground_color = console_screen_buffer_info.wAttributes;
			SetConsoleTextAttribute(std_out_handle, FOREGROUND_RED);
			//std::wcout << L"[[Setting completed]]Restart the computer to take effect!!!" << std::endl;
			std::wcout << L"【设置完毕】重启电脑生效！！！" << std::endl;
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), foreground_color);
		}
	} while (number != 0);

	return 0;
}
